package com.distribute.application.api;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;
import com.distribute.framework.core.lang.Protocol;
import com.distribute.framework.core.web.helper.ParamHelper;
import com.distribute.framework.core.web.helper.Utils;
import com.distribute.framework.model.SrvApi;
import com.distribute.framework.model.SrvApiClient;
import com.distribute.framework.model.SrvOauth;

@Aspect
@Order(2)
@Configuration
public class ApiInterceptor{

	@Around("execution(public com.distribute.framework.core.lang.Protocol com.distribute.application.api..*Controller.*(..))")
	 public Object afterInvoke(ProceedingJoinPoint joinPoint) throws Throwable {
    	Utils.getServletResponse().setHeader("Access-Control-Allow-Origin", "*");//跨域设置
    	Object controller = joinPoint.getTarget();
    	MethodSignature ms = (MethodSignature)joinPoint.getSignature();
		BaseApiController baseApiController = (BaseApiController) controller;
		
		HttpServletRequest request = Utils.getServletRequest();
		HttpServletResponse response = Utils.getServletResponse();
		
		Map requestParams = request.getParameterMap();
		
		String method = request.getServletPath();
		
		if (method.indexOf(".wx")==-1) {
			
			String timestamp = "";
			String appid = "";
			try{
				timestamp = ParamHelper.getString(requestParams,"timestamp");//时间戳
				appid = ParamHelper.getString(requestParams,"appid");//appid
				String token = ParamHelper.getString(requestParams,"token");//用户标识
				String sign = ParamHelper.getString(requestParams,"sign");//参数签名
				Double lat = ParamHelper.getDouble(requestParams,"lat");//经度
				Double lng = ParamHelper.getDouble(requestParams,"lng");//纬度
				
				if(Utils.empty(timestamp)) {
					return (new Protocol(false,"参数timestamp不能为空","invalid_param"));
				}
				if(Utils.empty(appid)) {
					return (new Protocol(false,"参数appid不能为空","invalid_param"));
				}
				if(Utils.empty(sign)) {
					return (new Protocol(false,"参数sign不能为空","invalid_param"));
				}
				if(!timestamp.matches("[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2}")){
					return (new Protocol(false,"参数timestamp格式错误，应该为yyyy-MM-dd HH:mm:ss","invalid_param"));
				}
				
				Date timeStamp = Utils.date(timestamp, "yyyy-MM-dd HH:mm:ss");
//				if(Math.abs(new Date().getTime()-timeStamp.getTime())>1000*60*10) {
//					return (new Protocol(false,"无效的调用时间","invalid_timestamp"));
//				}
				
				SrvApiClient apiClient = SrvApiClient.where.sacClient(appid).sacStatus((short)1).get();
				if(apiClient==null) {
					return (new Protocol(false,"无效的客户端","invalid_client"));
				}
				Map clientParamMap = (Map) requestParams;
				
				SrvOauth srvOauth = null;
				if(!Utils.empty(token)){
					srvOauth = SrvOauth.where.soApiClient(apiClient.getId()).soToken(token).get();
				}
				String strMethod=method;
				SrvApi srvApi = SrvApi.where.saNamespace(strMethod).get();
				if(srvApi==null)
					return (new Protocol(false,"调用接口名无效 - "+strMethod,"invalid_method"));
				if(srvApi.getSaStatus().shortValue()!=1)
					return (new Protocol(false,"调用接口正在测试中，请联系管理员 - "+strMethod,"invalid_method"));
				
				//要验证的参数
				List<String> verifyKeys = new ArrayList();
				verifyKeys.add("appid");
				verifyKeys.add("token");
				verifyKeys.add("timestamp");
				
				List<Map> paramInfos = ApiHelper.getParamInfos(baseApiController.getClass(),  ms.getMethod().getName());//参数结构描述
				if(paramInfos==null)paramInfos = new ArrayList<Map>();
				for(Map info:paramInfos){
					String type = (String) info.get("type");//参数类型
					String name = (String) info.get("name");//参数名称
					verifyKeys.add(name);
					String notnull = (String) info.get("notnull");//是否不能为空
					String defaultValue = (String) info.get("defaultValue");//默认值
					Object value = clientParamMap.get(name);//参数值
					if(value==null && Utils.equals(notnull, "true")){
						return (new Protocol(false,"接口["+strMethod+"]参数"+name+"不能为空","invalid_param"));
					}else if(value==null){//传来空值
						value = Utils.empty(defaultValue)?null:defaultValue;
					}
				}	
				
				if(srvOauth==null && srvApi.getSaOauth().shortValue()==1){
					//检验签名
					if(!ApiHelper.verifySign(requestParams,apiClient.getSacSecret(), sign,verifyKeys.toArray(new String[]{}))) {
						return (new Protocol(false,"参数签名验证失败","invalid_sign"));
					}
					return (new Protocol(false,"接口["+strMethod+"]需要用户授权","invalid_token"));
				}
				
				baseApiController.setApi(srvApi.getId());
				baseApiController.setClient(apiClient.getId());
				baseApiController.setLat(lat);
				baseApiController.setLng(lng);
				baseApiController.setSrvApi(srvApi);
				baseApiController.setSrvApiClient(apiClient);
				if(srvOauth!=null)
					baseApiController.setUid(srvOauth.getSoUserId());
				
			}catch(Error ex){
				ex.printStackTrace();
				return (new Protocol(false,"系统繁忙","system_error_exception"));
			}catch(Exception ex){
				ex.printStackTrace();
				return (new Protocol(false,"系统繁忙","system_error_exception"));
			}
		}
		
		Protocol returnValue = (Protocol) joinPoint.proceed();
		
		return returnValue;
	} 	
	
}